#pragma once

#include"nocopy.hpp"
#include<iostream>
#include<string>
#include"Log.hpp"
#include<sys/types.h>
#include<sys/socket.h>
#include<cerrno>
#include<cstring>
#include"Comm.hpp"
#include"InetAddr.hpp"

#include <netinet/in.h>
#include <arpa/inet.h>
#include<strings.h> //bzero


//const static std::string defaultip="0.0.0.0";
const static uint16_t defaultport=8888;
const static int defaultfd=-1;
const static int defaultsize=1024;

class UdpServer:public nocopy
{
public:
    UdpServer(uint16_t port=defaultport)
    :_port(port),_sockfd(defaultfd)
    {}
    void Init()
    {
        //1.创建socket套接字
        _sockfd=socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd<0)//创建成功文件描述符返回 创建失败-1返回错误码被设置
        {
            lg.LogMessage(Fatal,"socket errr, %d : %s",errno,strerror(errno));
            exit(Socket_Err);
        }
        lg.LogMessage(Info,"socket success,sockfd: %d\n",_sockfd);
        //2.绑定指定网络信息
        struct sockaddr_in local;//栈中定义的
        bzero(&local,sizeof(local));//清零
        local.sin_family=AF_INET;
        //local.sin_addr.s_addr=inet_addr(_ip.c_str());
        local.sin_addr.s_addr=INADDR_ANY;//ip任意
        local.sin_port=htons(_port);
        //上述结构体虽然填完了，但没有设置进内核

        int n=bind(_sockfd,(struct sockaddr*)&local,sizeof(local));
        if(n!=0)
        {
            lg.LogMessage(Fatal,"bind errr, %d : %s",errno,strerror(errno));
            exit(Bind_Err);
        }
    }
    void Start()
    {
        //服务器永远不退出死循环
        char buff[defaultsize];
        size_t len=sizeof(buff);
        struct sockaddr_in peer;
        socklen_t socklen=sizeof(peer);
        for(;;)
        {                                   //len-1 字符串有\0
            ssize_t n=recvfrom(_sockfd,&buff,len-1,0,(struct sockaddr*)&peer,&socklen);
            //n代表实际收到的长度
            if(n>0)
            {
                InetAddr addr(peer);
                buff[n]=0;
                std::cout<<"["<<addr.PrintDebug()<<"]# "<<buff<<std::endl;
                sendto(_sockfd,&buff,len,0,(struct sockaddr*)&peer,socklen);
            }
        }
    }
    ~UdpServer(){}
private:
    uint16_t _port;
    int _sockfd;
};
